# identity.py
import os

import cv2
import base64
import json
import requests
from config import (
    SPARK_APPID, SPARK_APIKey, SPARK_APISecret,
    RESUME_IMG, REGISTERED_IMG, CAPTURED_IMG,
    FACE_COMPARE_URL
)
from utils.auth import assemble_url


def extract_face_from_resume(img_path, output_path):
    image = cv2.imread(img_path)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    detector = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
    faces = detector.detectMultiScale(gray, 1.3, 5)
    if len(faces) == 0:
        print("❌ 未从简历中检测到人脸！")
        return False
    x, y, w, h = faces[0]
    face_img = image[y:y+h, x:x+w]
    cv2.imwrite(output_path, face_img)
    print("✅ 已从简历中保存头像:", output_path)
    return True


def capture_face_from_camera(output_path):
    cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
    detector = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
    if not cap.isOpened():
        print("❌ 无法打开摄像头")
        return False
    print("📷 请对准摄像头，按下 's' 拍照，按 'q' 退出")
    while True:
        ret, frame = cap.read()
        if not ret:
            continue
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        faces = detector.detectMultiScale(gray, 1.3, 5)
        for (x, y, w, h) in faces:
            cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
        cv2.imshow("Press 's' to capture, 'q' to quit", frame)
        key = cv2.waitKey(1)
        if key == ord('s'):
            if len(faces) == 0:
                print("⚠️ 未检测到人脸，请重试")
                continue
            x, y, w, h = faces[0]
            face_img = frame[y:y+h, x:x+w]
            cv2.imwrite(output_path, face_img)
            print("✅ 已拍摄当前头像:", output_path)
            break
        elif key == ord('q'):
            print("🚪 已取消拍照")
            break
    cap.release()
    cv2.destroyAllWindows()
    return True


def verify_identity():
    if not extract_face_from_resume(RESUME_IMG, REGISTERED_IMG):
        return False
    if not capture_face_from_camera(CAPTURED_IMG):
        return False

    with open(REGISTERED_IMG, "rb") as f1, open(CAPTURED_IMG, "rb") as f2:
        img1 = base64.b64encode(f1.read()).decode()
        img2 = base64.b64encode(f2.read()).decode()

    body = {
        "header": {"app_id": SPARK_APPID, "status": 3},
        "parameter": {
            "s67c9c78c": {
                "service_kind": "face_compare",
                "face_compare_result": {
                    "encoding": "utf8",
                    "compress": "raw",
                    "format": "json"
                }
            }
        },
        "payload": {
            "input1": {"encoding": "jpg", "image": img1, "status": 3},
            "input2": {"encoding": "jpg", "image": img2, "status": 3}
        }
    }

    headers = {
        'content-type': "application/json",
        'host': 'api.xf-yun.com',
        'app_id': SPARK_APPID
    }

    try:
        response = requests.post(assemble_url(FACE_COMPARE_URL), data=json.dumps(body), headers=headers)
        data = response.json()
    except Exception as e:
        print("❌ 请求失败或响应非 JSON：", e)
        return False

    print("🎯 人脸比对响应：", json.dumps(data, indent=2, ensure_ascii=False))

    if "payload" not in data or "face_compare_result" not in data["payload"]:
        print("❌ 接口响应异常，message：", data.get("message") or data)
        return False

    try:
        encoded = data["payload"]["face_compare_result"]["text"]
        decoded = json.loads(base64.b64decode(encoded).decode())
        score = decoded.get("score", 0)
        print(f"✅ 人脸相似度得分：{score:.4f}")
        return score >= 0.0
    except Exception as e:
        print("❌ 结果解析失败：", e)
        return False


def verify_identity_web(registered_face_path, captured_face_path):
    """
    Web API专用的人脸验证函数
    参数：
        registered_face_path: 注册人脸图片路径
        captured_face_path: 捕获人脸图片路径
    返回：
        float: 相似度分数 (0.0-1.0)
    """
    try:
        # 检查文件是否存在
        if not os.path.exists(registered_face_path):
            print(f"❌ 注册人脸文件不存在: {registered_face_path}")
            return 0.0

        if not os.path.exists(captured_face_path):
            print(f"❌ 捕获人脸文件不存在: {captured_face_path}")
            return 0.0

        # 读取两张图片并转换为base64
        with open(registered_face_path, "rb") as f1:
            img1 = base64.b64encode(f1.read()).decode()

        with open(captured_face_path, "rb") as f2:
            img2 = base64.b64encode(f2.read()).decode()

        # 构建请求体
        body = {
            "header": {"app_id": SPARK_APPID, "status": 3},
            "parameter": {
                "s67c9c78c": {
                    "service_kind": "face_compare",
                    "face_compare_result": {
                        "encoding": "utf8",
                        "compress": "raw",
                        "format": "json"
                    }
                }
            },
            "payload": {
                "input1": {"encoding": "jpg", "image": img1, "status": 3},
                "input2": {"encoding": "jpg", "image": img2, "status": 3}
            }
        }

        headers = {
            'content-type': "application/json",
            'host': 'api.xf-yun.com',
            'app_id': SPARK_APPID
        }

        # 发送请求
        try:
            response = requests.post(assemble_url(FACE_COMPARE_URL), data=json.dumps(body), headers=headers)
            data = response.json()
            print("🎯 人脸比对响应：", json.dumps(data, indent=2, ensure_ascii=False))
        except Exception as e:
            print("❌ 请求失败或响应非 JSON：", e)
            return 0.0

        # 解析响应
        if "payload" not in data or "face_compare_result" not in data["payload"]:
            print("❌ 接口响应异常，message：", data.get("message") or data)
            return 0.0

        try:
            encoded = data["payload"]["face_compare_result"]["text"]
            decoded = json.loads(base64.b64decode(encoded).decode())
            score = decoded.get("score", 0)
            print(f"✅ 人脸相似度得分：{score:.4f}")
            return float(score)  # 返回浮点数分数
        except Exception as e:
            print("❌ 结果解析失败：", e)
            return 0.0

    except Exception as e:
        print(f"❌ 人脸验证过程出错: {str(e)}")
        return 0.0

